<?php

class XaFeedsFileFetcherResult extends FeedsFileFetcherResult {

  /**
   * Overrides parent:getRaw().
   */
  public function getRaw() {
    $content = $this->file_get_contents_utf8($this->file_path);
    return $this->sanitizeRaw($content);
  }

  /**
   * Sanitize the file in place. Currently supported sanitizations:
   *
   * - Remove BOM header from UTF-8 files.
   *
   * @param string $filepath
   *   The file path of the file to be sanitized.
   * @return
   *   The file path of the sanitized file.
   */
  public function sanitizeFile($filepath) {
    $handle = fopen($filepath, 'r');
    $line = fgets($handle);
    fclose($handle);

    $encoding = mb_detect_encoding($line, 'UTF-8', true);
    if ($encoding !== 'UTF-8') {
      $convert = TRUE;
    }

    if (substr($line, 0, 3) == pack('CCC', 0xef, 0xbb, 0xbf)) {
      $remove_bom = TRUE;
    }

    if ($convert || $remove_bom) {
      $contents = $this->file_get_contents_utf8($filepath);

      if ($remove_bom) {
        $contents = substr($contents, 3);
      }

      $status = file_put_contents($filepath, $contents);
      if ($status === FALSE) {
        throw new Exception(t('File @filepath is not writeable.', array('@filepath' => $filepath)));
      }
    }

    return $filepath;
  }

  protected function file_get_contents_utf8($fn) {

    $content = file_get_contents($fn);

    $encoding = mb_detect_encoding($content, 'UTF-8', true);
    if ($encoding == 'UTF-8') {
      return $content;
    }
    else {
      return iconv('GB2312', 'UTF-8//IGNORE', $content);
    }
  }
}

class XaFeedsFileFetcher extends FeedsFileFetcher {

  public function fetch(FeedsSource $source) {
    $source_config = $source->getConfigFor($this);

    // Just return a file fetcher result if this is a file.
    if (is_file($source_config['source'])) {
      return new XaFeedsFileFetcherResult($source_config['source']);
    }

    // Batch if this is a directory.
    $state = $source->state(FEEDS_FETCH);
    $files = array();
    if (!isset($state->files)) {
      $state->files = $this->listFiles($source_config['source']);
      $state->total = count($state->files);
    }
    if (count($state->files)) {
      $file = array_shift($state->files);
      $state->progress($state->total, $state->total - count($state->files));
      return new XaFeedsFileFetcherResult($file);
    }

    throw new Exception(t('Resource is not a file or it is an empty directory: %source', array('%source' => $source_config['source'])));
  }

  public function sourceForm($source_config) {
    $form = parent::sourceForm($source_config);

    $css = <<<eof
  .form-item-feeds-feedscsvparser-delimiter,
  .form-item-feeds-feedscsvparser-no-headers,
  .form-item-feeds-feedscsvparser-encoding,
  .feeds-file-info { display:none !important; }
eof;
    drupal_add_css($css, array('type' => 'inline'));

    return $form;
  }
}